﻿using System.Collections.Generic;
using System.Threading.Tasks;
using System.Windows;
using P4 = Red.Core.Perforce;

namespace Red.Controls.SourceControl
{
    public class UIHelper
    {
        public Window Owner { get; set; }

        public P4.Mediator SourceControl { get; set; }

        public string File { get; set; }

        public async Task GetLatest()
        {
            await GetLatest( new [] { File }, SourceControl );
        }

        public async Task<bool> Checkout()
        {
            return await Checkout( new[] { File }, Owner, SourceControl );
        }

        public async Task<bool> MarkForAdd()
        {
            return await MarkForAdd( new[] { File }, Owner, SourceControl );
        }

        public async Task<bool> Revert()
        {
            return await Revert( new[] { File }, Owner, SourceControl );
        }

        public static async Task GetLatest( IEnumerable<string> files, P4.Mediator sourceControl )
        {
            await Task.Run( () => { sourceControl.GetLatestNoReturn( files ); } );
        }

        private static async Task<int> PendingChangelistInteraction( Window owner, P4.Mediator sourceControl )
        {
            var selectPendingChangelist = new SelectPendingChangelist() { Owner = owner, SourceControl = sourceControl };

            int changelistId = -1;

            if ( selectPendingChangelist.Show() )
            {
                await Task.Run( () =>
                {
                    ViewModels.PendingChangelistInfo changelist = selectPendingChangelist.ViewModel.SelectedChangelist;

                    if ( changelist is ViewModels.NewPendingChangelistInfo )
                    {
                        changelist.Id = sourceControl.CreateChangelist( changelist.Description );
                    }
                    else
                    {
                        sourceControl.UpdateChangelist( changelist.Id, changelist.Description );
                    }
                    changelistId = changelist.Id;
                } );
            }

            return changelistId;
        }

        public static async Task<bool> Checkout( IEnumerable<string> files, Window owner, P4.Mediator sourceControl )
        {
            int changelistId = await PendingChangelistInteraction( owner, sourceControl );

            if ( changelistId > 0 )
            {
                await Task.Run( () => { sourceControl.CheckoutFiles( files, changelistId ); } );

                return true;
            }

            return false;
        }

        public static async Task<bool> MarkForAdd( IEnumerable<string> files, Window owner, P4.Mediator sourceControl )
        {
            int changelistId = await PendingChangelistInteraction( owner, sourceControl );

            if ( changelistId > 0 )
            {
                await Task.Run( () => { sourceControl.AddFiles( files, changelistId ); } );

                return true;
            }

            return false;
        }

        public static async Task<bool> Delete( IEnumerable<string> files, Window owner, P4.Mediator sourceControl )
        {
            int changelistId = await PendingChangelistInteraction( owner, sourceControl );

            if ( changelistId > 0 )
            {
                await Task.Run( () => { sourceControl.DeleteFiles( files, changelistId ); } );

                return true;
            }

            return false;
        }

        public static async Task<bool> Revert( IEnumerable<string> files, Window owner, P4.Mediator sourceControl )
        {
            var revertDialog = new RevertFilesDialog() { Owner = owner };

            foreach ( string file in files )
            {
                revertDialog.Files.Add( file );
            }

            if ( revertDialog.Show() )
            {
                IEnumerable<Perforce.P4.Changelist> changelists = null;

                // Retrieve associated changelists
                if ( revertDialog.DeleteEmptyChangelists )
                {
                    await Task.Run( () => { changelists = sourceControl.GetChangelists( files ); } );
                }

                // Revert files
                await Task.Run( () => { sourceControl.RevertFiles( files, revertDialog.RevertUnchangedOnly ); } );

                // Delete empty changelists
                if ( revertDialog.DeleteEmptyChangelists )
                {
                    await Task.Run
                    (
                        () =>
                        {
                            foreach ( var cl in changelists )
                            {
                                if ( cl.Files.Count == 0 && !cl.Shelved )
                                {
                                    sourceControl.DeleteChangelist( cl );
                                }
                            }
                        }
                    );
                }

                return true;
            }

            return false;
        }
    }
}
